package com.cheng.example.book.advise151.chap1;

/**
 * https://www.cnblogs.com/selene/p/5844686.html
 * 建议18：避免instanceof非预期结果
 *
 * 1、null不是任何对象的子类型，这个非常重要
 * 2、instanceof两边的属性需要有继承关系
 *
 * 这个很不错的样子
 */
import java.util.Date;

public class Client18 {
    public static void main(String[] args) {
        // String对象是否是Object的实例 true
        boolean b1 = "String" instanceof Object;
        // String对象是否是String的实例 true
        boolean b2 = new String() instanceof String;
        // Object对象是否是String的实例 false
        boolean b3 = new Object() instanceof String;
        // 拆箱类型是否是装箱类型的实例 编译不通过
        //这句话编译不通过，为什么呢？因为'A'是一个char类型，也就是一个基本类型，不是一个对象，instanceof只能用于对象的判断，不能用于基本类型的判断。
//        boolean b4 = 'A' instanceof Character;


        // 空对象是否是String的实例 false
        //，这是instanceof特有的规则，若做操作数为null，结果就直接返回false，不再运算右操作数是什么类。
        // 这对我们的程序非常有利，在使用instanceof操作符时，
        // 不用关心被判断的类(也就是左操作数)是否为null，这与我们经常用到的equals、toString方法不同。
        boolean b5 = null instanceof String;


        // 转换后的空对象是否是String的实例 false
        // null是一个万用类型，也就是说它可以没类型，即使做类型转换还是个null。
        boolean b6 = (String) null instanceof String;


        // Date是否是String的实例 编译不通过

        //因为Date类和String没有继承或实现关系，所以在编译时就直接报错了，
        // instanceof操作符的左右操作数必须有继承或实现关系，否则编译会失败。
//        boolean b7 = new Date() instanceof String;


        // 在泛型类型中判断String对象是否是Date的实例 false

        //编译不通过，非也，编译通过了，返回值为false，T是个String类型，于Date之间没有继承或实现关系，
        // 为什么"t instanceof Date"会编译通过呢？那是因为Java的泛型是为编码服务的，在编译成字节码时，
        // T已经是Object类型了传递的实参是String类型，也就是说T的表面类型是Object，
        // 实际类型是String，那么"t instanceof Date"等价于"Object instanceof Date"了，所以返回false就很正常了。
        boolean b8 = new GenericClass<String>().isDateInstance("");

        System.out.println(b8);

    }
}

class GenericClass<T> {
    // 判断是否是Date类型
    public boolean isDateInstance(T t) {
        return t instanceof Date;
    }

}